﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace LoanProject.Models
{
    public partial class Loan
    {
        private decimal Interest { get; set; }
        private const int DefaultUserId = 1;
        readonly DateTime _defaultStartDate = DateTime.Today;
        public List<LoanMonthly> LoanMonthlys = new List<LoanMonthly>();
        private int _period = 0;
        private List<Condition> _conditions;
        public List<Condition> k = new List<Condition>();
        

        public Loan()
        {
            Interest = 6.125M;
            StartDate = _defaultStartDate;
            UserId = DefaultUserId;
         Condition c1 = new Condition { DateFrom = Convert.ToDateTime("01/03/2557"), DateTo = Convert.ToDateTime("01/03/2558"), Interest = 3.5m };
         Condition c2 = new Condition { DateFrom = Convert.ToDateTime("01/03/2558"), DateTo = Convert.ToDateTime("01/03/2559"), Interest = 3.5m };
         Condition c3 = new Condition { DateFrom = Convert.ToDateTime("01/03/2559"), DateTo = Convert.ToDateTime("01/03/2560"), Interest = 6.05m };
         k.Add(c1);
         k.Add(c2);
         k.Add(c3);
        }

        public void Cal()
        {
            var conditions = new List<Condition> {new Condition() };
            Cal(ref conditions, Principle, StartDate, Installment);
        }

        public void Cal(Condition condition)
        {
            var conditions = new List<Condition>() { condition };
            _conditions = conditions;
            Cal(ref conditions, tempPrinciple: Principle, currentMonth: StartDate, payMonthly: Installment);
        }

        public void Cal(List<Condition> conditions)
        {
            Cal(ref conditions, tempPrinciple: Principle, currentMonth: StartDate, payMonthly: Installment);
        }
        
        
        private decimal Cal(ref List<Condition> conditions, decimal tempPrinciple, DateTime currentMonth, decimal payMonthly)
        {
            if (currentMonth.Year < 2000)
            {
                currentMonth = Convert.ToDateTime("01/03/2557");
            }
            while (tempPrinciple > 0)
            {
                _period++;
                decimal interest = Interest;
                foreach (var condition in k)
                {
                    if (currentMonth >= condition.DateFrom && currentMonth < condition.DateTo)
                    {
                        interest = condition.Interest;
                        break;
                    }
                }
                decimal mInterest = (interest * DateTime.DaysInMonth(currentMonth.Year, currentMonth.Month)) * tempPrinciple / (100 * 365);
                decimal principle = payMonthly - mInterest;
                var ml = new LoanMonthly()
                             {
                                 DateTime = currentMonth,
                                 RemainPrinciple = new Cell { Value = tempPrinciple - principle, Text = tempPrinciple.ToString("N2") },
                                 Installment = new Cell { Value = payMonthly, Text = payMonthly.ToString("N2") },
                                 InterestAmount = new Cell { Value = mInterest, Text = mInterest.ToString("N2") },
                                 Interest = new Cell { Value = mInterest, Text = interest.ToString() },
                                 PaidPrinciple = new Cell { Value = principle, Text = principle.ToString("N2") },
                                 Period = _period
                             };
                LoanMonthlys.Add(ml);
                if (tempPrinciple - principle < 0)
                {
                    return 0;
                }
                else
                {
                    return Cal(ref conditions, tempPrinciple - principle, currentMonth.AddMonths(1), payMonthly);
                }
            }
            return 0;
        }

        public void ReCalculate()
        {
            ReCalculate(1);
        }

        public void ReCalculate(int period)
        {
            var tempLoanMonthly = this.LoanMonthlys.First(x => x.Period == period);
            foreach (var remove in this.LoanMonthlys.Where<LoanMonthly>(x => x.Period > period)){
                LoanMonthlys.Remove(remove);
            }
            Cal(ref _conditions, tempLoanMonthly.RemainPrinciple.Value, tempLoanMonthly.DateTime, tempLoanMonthly.Installment.Value);
        }

        public bool SaveLoan()
        {
            try
            {
                var context = new DataModelContainer();
                context.Loans.AddObject(this);
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return true;
        }
    }
}